#include "user_inf_aduf.h"
#include "product_manage.h" //
#include "user_manage.h"    //
#include "timesUs.h"
#include <termios.h>

#define LOAD_BR "file_data/user_BR_inf/"
typedef union elem_vector TYPE_RECORD;
char record_gfind_v[][30] = {"物资编号", "物资名称", "借出", "归还", "借还数", "时间"};
char record_gscanf_matrl[][15] = {"%s", "%s", "%s", "%d", "%s"};

void read_record_inf(char *load);
void user_BR_fwrite_vector(vector v);
void renew_data(vector v, char *load);
void logging(TYPE_RECORD *data, char *load);
vector records_read_inf(const char *file_name);
void show_B_inf(TYPE_RECORD *data);
void look_product_inf(vector v);
void look_BR_inf(vector v);
int find_user_prt(const void *dast, const void *str, size_t mod);
void borrow_product(vector v_product, vector us_v);
void return_product(vector v_product, vector us_v);
void show_BR_recode_inf(TYPE_RECORD *data);
void look_record_inf(vector v);
int user_BR_sort_link_cmp(const void *dast, const void *str);
vector user_BR_read_file_data(void);
vector user_BR_link_to_vector(list_inf l);
list_inf user_BR_vector_to_link(vector v);
void load_Init(union elem_vector *user);
void user_inf_upd(union elem_vector *user_inf);

char load_inf[100] = "";
char record_load_inf[100] = "";

// 改用户密码
void user_upd_passwd(union elem_vector *user_inf)
{
    char pw_temp[100] = "";
    int i = 1;
    printf("---------修改密码-----------\n");
    printf("请输入旧密码:");

    while (i < 4)
    {
        scanf("%s", pw_temp);

        // 密码格式检测 + MD5加密
        getchar();
        if (0 != strcmp(user_inf->_USER.md5_passwd, pw_temp))
        {
            printf("密码错误，请再次输入(%d / 3):", i++);
        }
    }

    printf("请输入新密码:");
}

// 用户查看已借用的货物
void look_borrowed_product(vector v)
{
    int i = 0, j = 0;
    while (i < v->size)
    {
        while (j < 5)
        {
        }
    }
}
// 查看修改用户信息
void user_inf_upd(union elem_vector *user_inf)
{
    int i = 0;
    char YN_Del, c;
    union elem_vector data_temp = *user_inf;

    while (1)
    {
        user_show_inf(&data_temp);
        printf("\n");

        for (i = 0; i < PRODUCT_PROJECT_NUM; i++)
        {
            printf("\n%d.修改%s", i + 1, user_gfind_v[i]);
        }

        printf("\n0.修改结束\n");
        printf("\nQ.直接退出(不保存修改数据)\n");

        printf("\n:>");
        YN_Del = getchar();
        while ('\n' != YN_Del && '\n' != (c = getchar())) // 一个回车也会进入下一循环
            ;

        if ('Q' == YN_Del && 'q' == YN_Del)
        {
            return;
        }

        if ('0' == YN_Del)
        {
            break;
        }

        if ('1' > YN_Del || (PRODUCT_PROJECT_NUM + '0') < YN_Del) // 如果不是这个选项区间就重新
        {
            continue;
        }

        user_Vector_Upd_switch(&data_temp, YN_Del - '0'); // 进入选择输入
    }

    printf("是否保存操作？(Y/N)");

    YN_Del = getchar();
    while ('\n' != YN_Del && '\n' != (c = getchar())) // 一个回车也会进入下一循环
        ;

    if (YN_Del == 'Y' || YN_Del == 'y')
    {
        *user_inf = data_temp;

        printf("更新成功\n");
    }

    return;
}

// 更新日志
void logging(TYPE_RECORD *data, char *load)
{
    FILE *fp = fopen(load, "ab");
    fwrite(data, sizeof(union elem_vector), 1, fp);
    fclose(fp);
}

// 日志信息读取进入顺序表
void Recode_Main(union elem_vector *user)
{

    vector v_record = NULL;

    v_record = records_read_inf(record_load_inf);
}

// 更新地址
void load_Init(union elem_vector *user)
{
    memset(load_inf, '\0', sizeof(load_inf));
    memset(record_load_inf, '\0', sizeof(load_inf));

    strcat(load_inf, LOAD_BR); // 赋值用户货物地址
    strcat(load_inf, user->_USER.ID);
    strcat(load_inf, "_BR_inf.bin");

    strcat(record_load_inf, LOAD_BR); // 赋值用户日志地址
    strcat(record_load_inf, user->_USER.ID);
    strcat(record_load_inf, "_record.bin");
}

// 用户借还货主函数 v_product货物信息  user 用户信息
void BR_Main(vector v_product, union elem_vector *user)
{
    // 每次登录用户都会将路径更新
    char rtn, c;
    vector vc = NULL;
    // vector v_record = NULL;

    load_Init(user); // 更新地址
    // v_record = records_read_inf(record_load_inf); // 日志信息读取进

    vc = records_read_inf(load_inf); // 信息读取进入顺序表

    while (1)
    {
        system("clear");
        printf("--------------------\n1.货物查找\n2.借货\n3.归还\n4.日志\n5.个人信息\n6.已借货物\n7.修改密码\n0.退出\n::>");

        while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
            ;
        switch (rtn)
        {

        case '1': // 改密码
            product_Vector_Find(v_product);
            break;

        case '2':
            borrow_product(v_product, vc);
            break;

        case '3':
            return_product(v_product, vc);
            break;

        case '4':
            read_record_inf(record_load_inf);
            break;

        case '5':
            user_show_inf(user);
            // user_inf_upd(v_product, vc);
            break;

        case '6':
            look_BR_inf(vc);
            break;

        case '7': // 改密码

            break;

        case '0':
            product_Update_data(v_product);
            return;
            break;

        default:
            break;
        }
    }
}

// 直接读数据进入vector//这个没用
void user_BR_fwrite_vector(vector v)
{
    FILE *fp = fopen("inf.bin", "w");
    fread(v->buff, sizeof(v->buff) * v->size, 1, fp);
    fclose(fp);
}

// 更新用户货物信息数据
void renew_data(vector v, char *load)
{
    FILE *fp = fopen(load, "w");
    fwrite(v->buff, sizeof(TYPE_RECORD) * v->size, 1, fp);
    fclose(fp);
}

// 读取文件信息进顺序表(不需要排序操作)
vector records_read_inf(const char *file_name)
{

    FILE *fp = fopen(file_name, "a+"); // 有了就读，没了就创建
    vector v = vector_create(20);
    TYPE_RECORD data;
    printf("地址%s\n", file_name);

    fseek(fp, 0, SEEK_SET);                          // 回到文件开头
    while (fread(&data, sizeof(TYPE_RECORD), 1, fp)) // 遍历文件读取结构数据
    {
        if (strlen((char *)&data) == 0)
        {
            continue;
        }
        vector_push_back(v, data);
    }

    fclose(fp);
    return v;
}

// 逆序读日志信息
void read_record_inf(char *load)
{
    FILE *fp = fopen(load, "r");
    TYPE_RECORD data;
    char temp[10] = "", c, rtn;
    int j = 1;

    fseek(fp, 0, SEEK_END);

    printf("-----------日志信息（按下回车依次打印,输入Q停止）---------------\n");

    while ((0 == fseek(fp, -(sizeof(TYPE_RECORD) * j), SEEK_END)) && fread(&data, sizeof(TYPE_RECORD), 1, fp))
    {
        j++;
        show_B_inf(&data);
        while ('\n' != (rtn = getchar()) && '\n' != (c = getchar()))
            ;
        if ('q' == rtn || 'Q' == rtn)
        {
            return;
        }
    }
}

// 显示日志信息信息
void show_B_inf(TYPE_RECORD *data)
{
    printf("%s: %s ", "货物ID", data->_BR_INF.ID);
    printf("%s: %s ", "货物名", data->_BR_INF.name);
    printf("%s: %d ", data->_BR_INF.mark ? "货物借入数" : "货物归还数", data->_BR_INF.BR_num);
    printf("%s: %s ", "操作时间", data->_BR_INF.run_time);
}

// 遍历显示
void look_product_inf(vector v)
{
    char c, rtn;
    int i = 0, j = 0;

    printf("（按下回车依次打印,按Q结束）\n");
    while (i < v->size)
    {
        j = 0;
        while (i < v->size && j < 5) // 每次打印5个
        {
            if (0 == strlen(v->buff[i]._BR_INF.ID))
            {
                i++;
                continue;
            }
            printf("%s: %s ", record_gfind_v[0], v->buff[i]._USER_BR.ID);
            printf("%s: %s ", record_gfind_v[1], v->buff[i]._USER_BR.name);
            printf("%s: %d \n", record_gfind_v[2], v->buff[i]._USER_BR.num);

            i++;
            j++;
        }

        if (i >= v->size)
        {
            break;
        }

        while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
            ;

        if ('Q' == rtn && 'q' == rtn)
            break;
        i++;
    }
    printf("end");
}

// 遍历显示借入的货物信息
void look_BR_inf(vector v)
{
    char c, rtn;
    while (1)
    {
        printf("--------借入的货物信息-------");
        look_product_inf(v);
        printf("\n是否重新打印(Y/N):");
        while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
            ;

        if ('Y' != rtn && 'y' != rtn)
            return;
    }
}

// 匹配用户自己的货物信息 返回1是匹配失败返回0是匹配成功，用在find上
int find_user_prt(const void *dast, const void *str, size_t mod)
{
    TYPE_RECORD *temp = (TYPE_RECORD *)dast;
    if (mod)
    {
        if (strlen(temp->_USER_BR.ID) != strlen(str))
            return 1;

        if (0 == strcmp(temp->_USER_BR.ID, str)) //((struct _role_inf *)dast)->ID == ((struct _role_inf *)str)->ID
            return 0;
    }
    else
    {
        if (NULL != strstr(temp->_USER_BR.ID, str))
            return 0;
    }
    return 1;
}

// 子功能 用户借货
void borrow_product(vector v_product, vector us_v) // BR
{
    TYPE_RECORD *temp = NULL, *us_ptd = NULL;
    TYPE_RECORD *logging_data = (TYPE_RECORD *)calloc(1, sizeof(TYPE_RECORD));
    char c, rtn;
    unsigned int num = 0;
    void *data = (void *)malloc(sizeof(TYPE_RECORD));
    while (1)
    {
        printf("------------请输入要借用的货物ID(输入Q退出)---------\n");

        scanf("%s", (char *)data); // 数据放入堆区空间
        getchar();
        if ('Q' == *(char *)data || 'q' == *(char *)data)
        {
            return;
        }

        if (NULL != (temp = product_find_data(v_product, data, product_func_array[0], 1)))
        { // 查自己的货
            if (NULL == (us_ptd = product_find_data(us_v, data, find_user_prt, 1)))
            { // 如果自己没有该货创建信息
                us_ptd = (TYPE_RECORD *)malloc(sizeof(TYPE_RECORD));

                strcpy(us_ptd->_USER_BR.ID, temp->_PRODUCT.ID);
                strcpy(us_ptd->_USER_BR.name, temp->_PRODUCT.name); // 赋值相关信息
                us_ptd->_USER_BR.num = 0;                           // 重新置0
            }

            product_show_inf(temp);
            printf("\n请输入要借用的货物数量：");

            scanf("%d", &num);
            getchar();
            // fgets(data, sizeof(TYPE_RECORD), stdin);

            printf("确定借%d个？(Y/N):", num >= temp->_PRODUCT.size ? temp->_PRODUCT.size : num);

            while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
                ;

            if ('y' != rtn && 'Y' != rtn)
            {
                continue;
            }

            // （抽象）
            num > temp->_PRODUCT.size ? ({
                us_ptd->_USER_BR.num += temp->_PRODUCT.size;
                temp->_PRODUCT.size = 0;
            })
                                      : ({ 
               us_ptd->_USER_BR.num += num;
                temp->_PRODUCT.size -= num ; });

            vector_push_back(us_v, *us_ptd); // 数据赋值后尾插

            strcpy(logging_data->_BR_INF.ID, us_ptd->_USER_BR.ID);
            strcpy(logging_data->_BR_INF.name, us_ptd->_USER_BR.name);
            logging_data->_BR_INF.mark = 1;
            logging_data->_BR_INF.BR_num = num;

            Year_moth_day();
            Hour_Min_Sec();

            // memset(logging_data->_BR_INF.run_time, '\0', sizeof(logging_data->_BR_INF.run_time));

            sprintf(logging_data->_BR_INF.run_time, "%d-%d-%d %d:%d:%d", arr_time[0], arr_time[1], arr_time[2], arr_time[3], arr_time[4], arr_time[5]);
            logging(logging_data, record_load_inf);

            printf("继续？(Y/N)");

            while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
                ;
            if ('y' != rtn && 'Y' != rtn)
            {
                renew_data(us_v, load_inf);
                return;
            }
        }
        else
        {

            printf("no find the %s(继续请回车)\n", (char *)data);
            while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
                ;
        }
        // system("clear");
    }
}

// 密码回显*
void input_passwd(char *input)
{
    struct termios old_tio, new_tio;
    unsigned char c;
    int i = 0;

    /* 获取终端属性 */
    tcgetattr(STDIN_FILENO, &old_tio);

    /* 设置新的终端属性 */
    new_tio = old_tio;
    new_tio.c_lflag &= (~ICANON & ~ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &new_tio);
    while ((c = getchar()) != 'q')
    {
        if ('\n' == c)
            break;

        if (127 == c)
        {
            printf("\b \b");
            fflush(stdout);

            i--;

            input[i] = '\0';
            continue;
        }

        input[i] = c;

        printf("*");
        fflush(stdout);

        i++;
    }

    /* 恢复旧的终端属性 */
    tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);

    return;
}

// 子功能 用户还货// 要做输入检测########
void return_product(vector v_product, vector us_v)
{
    void *data = (void *)malloc(sizeof(TYPE_RECORD)); // 存放搜索ID的信息
    TYPE_RECORD *temp = NULL, *us_ptd = NULL;
    TYPE_RECORD *logging_data = (TYPE_RECORD *)calloc(1, sizeof(TYPE_RECORD));
    char c, rtn;
    int j = 0;
    unsigned int num = 0;

    while (1)
    {
        printf("------------请输入要归还的货物ID(输入Q退出)---------\n");
        printf("::>");

        scanf("%s", (char *)data); // 数据放入堆区空间
        getchar();
        if ('Q' == *(char *)data || 'q' == *(char *)data)
        {
            return;
        }

        // 查货
        if (NULL != (temp = product_find_data(v_product, data, product_func_array[0], 1)))
        {
            // 查自己的货
            if (NULL == (us_ptd = product_find_data(us_v, data, find_user_prt, 1)))
            {
                printf("你没有%s %s\n", temp->_PRODUCT.ID, temp->_PRODUCT.name);
                printf("继续？(Y/N)");

                while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
                    ;

                if ('y' != rtn && 'Y' != rtn)
                {
                    // system("clear");
                    return;
                }

                continue;
            }
            printf("你借出的货物信息如下:\n");

            show_B_inf(us_ptd); // 显示货信息
            printf("\n请输入要归还的货物数量：");

            scanf("%d", &num); // 要做输入检测########
            getchar();

            printf("确定还%d个？(Y/N):", num);
            while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
                ;
            if ('y' != rtn && 'Y' != rtn)
            {
                continue;
            }

            strcat(logging_data->_BR_INF.ID, us_ptd->_USER_BR.ID);
            strcat(logging_data->_BR_INF.name, us_ptd->_USER_BR.name);

            // （抽象）
            if (num >= us_ptd->_USER_BR.num)
            {
                temp->_PRODUCT.size += us_ptd->_USER_BR.num;
                logging_data->_BR_INF.BR_num = us_ptd->_USER_BR.num;
                us_ptd->_USER_BR.num = 0;
                memset(us_ptd, '\0', sizeof(union elem_vector));
            }
            else
            {
                logging_data->_BR_INF.BR_num = num;
                temp->_PRODUCT.size += num;
                us_ptd->_USER_BR.num -= num;
            }

            logging_data->_BR_INF.mark = 0;
            sprintf(logging_data->_BR_INF.run_time, "%d-%d-%d %d:%d:%d", arr_time[0], arr_time[1], arr_time[2], arr_time[3], arr_time[4], arr_time[5]);

            logging(logging_data, record_load_inf); // 日志记录

            printf("继续？(Y/N)");
            while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
                ;
            if ('y' != rtn && 'Y' != rtn)
            {
                renew_data(us_v, load_inf);
                return;
            }
        }
        else
        {
            printf("仓库没有此ID %s 货物相关信息请联系管理员(继续请回车,输入Q退出)\n", (char *)data);
            while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
                ;
        }
        // system("clear");
    }

    renew_data(us_v, load_inf);
}

// 显示日志信息（单个）
void show_BR_recode_inf(TYPE_RECORD *data)
{

    printf("%s: %s ", record_gfind_v[0], data->_BR_INF.ID);
    printf("%s: %s ", record_gfind_v[1], data->_BR_INF.name);

    if (data->_BR_INF.mark)
    {
        printf("%s", record_gfind_v[2]); // 借
    }
    else
    {
        printf("%s", record_gfind_v[3]); // 还
    }
    printf(": %d ", data->_BR_INF.BR_num);

    printf("%s: %s", record_gfind_v[5], data->_BR_INF.run_time);
}

// 打印日志记录的信息（遍历）(已迭代)
void look_record_inf(vector v)
{
    char c, rtn;
    int i = v->size, j = 0;

    printf("-----------日志信息（按下回车依次打印,输入Q停止）---------------");
    while (i--) // 从后往前遍历
    {
        j = 0;
        while (i && j < 5) // 每次打印5个
        {
            show_BR_recode_inf(&(v->buff[i]));
            printf("\n");

            i--;
            j++;
        }
        if (!i)
        {
            break;
        }

        while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
            ;

        if ('Q' == rtn && 'q' == rtn)
            break;
    }
    printf("end(回车结束)\n");
    while (('\n' != (rtn = getchar())) && ('\n' != (c = getchar())))
        ;
}

// 匹配ID排序的链表排序的cmp函数
int user_BR_sort_link_cmp(const void *dast, const void *str)
{
    struct _role_inf *p = (struct _role_inf *)dast;
    struct _role_inf *q = (struct _role_inf *)str;

    if (strcmp(p->ID, q->ID) >= 0)
        return 1;

    return -1;
}

// 读取数据文件放入顺序表
vector user_BR_read_file_data(void)
{
    list_inf l = NULL;
    vector vc = (vector)malloc(sizeof(struct _vector));
    size_t i = 0;
    l = link_create(); // 创建链表

    FILE *file = fopen(LOAD_BR, "rb");

    elem_type *temp = (elem_type *)calloc(1, sizeof(elem_type)); // 链表数据域

    while (fread(temp, sizeof(data_type), 1, file)) // 读文件存入链表
    {

        if (0 == strlen(temp->_PRODUCT.ID))
        {
            free(temp);
            temp = (data_type *)calloc(1, sizeof(data_type));
            continue;
        }

        printf("\n");

        link_push_back(l, temp);                          // 尾插，链表加节点，节点存入数据
        temp = (data_type *)calloc(1, sizeof(data_type)); // 再剔除
    }

    if (-1 == 0)
    {
        fprintf(stderr, "read_file_data::读取出错!\n");
        exit(1);
    }

    free(temp);

    link_sort(l, user_BR_sort_link_cmp); // 链表排序
    vc = user_BR_link_to_vector(l);      // 传入
    link_destory(l);                     // 销毁

    fclose(file);

    return vc;
}

// 将链表数据导入顺序表，链表不销毁
vector user_BR_link_to_vector(list_inf l)
{
    int i = 0;
    vector v = vector_create(l->size + l->size / 5);
    node *p = l->head->next;

    while (NULL != p)
    {
        vector_push_back(v, *p->data);
        p = p->next;
    }

    return v;
}

// 顺序表数据导入链表,源顺序表不销毁
list_inf user_BR_vector_to_link(vector v)
{
    int i = 0;
    list_inf l = link_create();
    node *p = l->head;

    while (i < v->size)
    {
        elem_type *temp = (elem_type *)malloc(sizeof(elem_type));
        *temp = v->buff[i++];
        link_push_back(l, temp); // 链表数据域是地址
    }

    return l;
}